package com.ruoyi.common.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.*;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * HttpClient4.3工具类
 */
public class HttpTools {
    protected static transient Log log = LogFactory.getLog(HttpTools.class);
    //请求和传输超时时间
    private static int SOCKET_TIME_OUT = 60000;
    private static int CONNECT_TIME_OUT = 60000;
    private static CookieStore cookieStore = null;

    //Http,post请求常用
    public static String postWsClient(String URL, Map<String, Object> paramMap) {
        String result = null;
        OutputStream os = null;  //输出
        HttpURLConnection conn = null;//获取httpURl连接对象
        InputStream inputStream = null; //输入
        try {
            java.net.URL url = new URL(URL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(10000);
            conn.setReadTimeout(20000);
            String paramStr = prepareParam(paramMap);
            conn.setDoOutput(true); //允许写出
            conn.setDoInput(true);  //允许写入
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");//请求方式
            // 默认application/x-www-form-urlencoded    application/json参数为json格式的   multipart/form-data 上传文件的
            // conn.setRequestProperty("Content-Type","application/json");
            os = conn.getOutputStream();
            os.write(paramStr.getBytes("utf-8"));
            os.flush();
            inputStream = conn.getInputStream();
            byte[] data = StreamTools.readInputStream(inputStream);
            result = new String(data, "UTF-8");
            conn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null)
                    os.close();
                if (inputStream != null)
                    inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * httpClient发送post请求
     */
    public static String httpClientSent(String url, Map paramMap) {
        String result = null;
        //1.创建HttpCient实例
        CloseableHttpClient httpClient = null;
        //2.创建httpPost(HttpGet)实例
        HttpPost httpPost = null;
        //3.设置请求和传输时间
        RequestConfig config = null;
        try {
            httpClient = HttpClients.createDefault();
            httpPost = new HttpPost(url);
            //httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0");//头信息
            //   httpPost.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
            config = RequestConfig.custom()
                    .setSocketTimeout(60000)   //设置读取超时时间
                    .setConnectTimeout(60000)  //设置超时时间60秒钟
                    .setRedirectsEnabled(false)
                 //   .setCookieSpec(CookieSpecs.STANDARD) //?
                    //  .setProxy(new HttpHost("175.44.108.244",2223))  //百度搜索代理ip
                    .build();
            httpPost.setConfig(config);

            //4.构建参数
            List formparams = postFormEncode(paramMap);
            httpPost.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));//GBK

            //5.执行请求
            CloseableHttpResponse response = httpClient.execute(httpPost);

            //6.获得响应
            System.out.println(response.getStatusLine().getStatusCode());
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity(); //获取返回实体
                result = EntityUtils.toString(entity, "utf-8");

             //   Header[] header = response.getHeaders("Set-Cookie"); //?
                // 解决中文乱码问题
             /*   StringEntity entity = new StringEntity(strParam, "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/x-www-form-urlencoded");
                httpPost.setEntity(entity);*/

                //  System.out.println("Content-Type："+entity.getContentType().getValue());//返回的内容类型
                /*InputStream inputStream = entity.getContent();   图片
                FileUtils.copyToFile(inputStream,new File("C:\\aaa.jpg")); 复制 */
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (httpClient != null) httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 获取本机的外网ip地址
     */
    public static String getIP() {
        String ip = "";
        String chinaz = "http://ip.chinaz.com";
        StringBuilder inputLine = new StringBuilder();
        String read = "";
        URL url = null;
        HttpURLConnection urlConnection = null;
        BufferedReader in = null;
        try {
            url = new URL(chinaz);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
            while ((read = in.readLine()) != null) {
                inputLine.append(read + "\r\n");
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        Pattern p = Pattern.compile("\\<dd class\\=\"fz24\">(.*?)\\<\\/dd>");
        Matcher m = p.matcher(inputLine.toString());
        if (m.find()) {
            String ipstr = m.group(1);
            ip = ipstr;
        }
        return ip;
    }

    //构建参数
    public static String prepareParam(Map<String, Object> paramMap) {
        StringBuffer sb = new StringBuffer();
        if (paramMap == null || paramMap.isEmpty()) {
            return "";
        } else {
            for (String key : paramMap.keySet()) {
                String value = (String) paramMap.get(key);
                if (sb.length() < 1) {
                    sb.append(key).append("=").append(value);
                } else {
                    sb.append("&").append(key).append("=").append(value);
                }
            }
        }
        return sb.toString();
    }

    //构建参数
    public static List<BasicNameValuePair> postFormEncode(Map<String, Object> data) {
        List formparams = new ArrayList();
        if (data != null && data.size() > 0) {
            for (Map.Entry i : data.entrySet()) {
                formparams.add(new BasicNameValuePair(StringTools.objString(i.getKey()), StringTools.objString(i.getValue())));
            }
        }
        return formparams;
    }


    //将map型转为表单请求参数型
    public static String urlencode(Map<String, Object> data, String enc) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        enc = "".equals(enc) || null == enc ? "UTF-8" : enc;  //GBK
        for (Map.Entry i : data.entrySet()) {
            sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", enc)).append("&");
        }
        return sb.toString();
    }

    public static void setCookieStore(HttpResponse httpResponse, String host) {
        cookieStore = new BasicCookieStore();
        // JSESSIONID
        if (null == httpResponse.getFirstHeader("Set-Cookie")) {
            cookieStore = null;
        } else {
            String setCookie = httpResponse.getFirstHeader("Set-Cookie").getValue();
            String JSESSIONID = setCookie.substring("JSESSIONID=".length(), setCookie.indexOf(";"));
            // 新建一个Cookie
            BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", JSESSIONID);
            cookie.setVersion(0);
            cookie.setDomain(host);
            cookie.setPath("/");
            cookieStore.addCookie(cookie);
        }
    }

    //==================================================================================================================

    /**
     * response返回通知
     */
    public static void responseShowInfo(HttpServletResponse response, String message) {
        PrintWriter writer = null;
        try {
            response.setCharacterEncoding("UTF8");//通知response以UTF-8发送
            response.setContentType("text/html;charset=UTF-8");  //设置浏览器以UTF-8打开     ...ext/html;charset=GBK
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            writer = response.getWriter();
            writer.print(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 需要凭证的get请求
     */
    public static String get(String[] credentials, String url) {
        String result = null;
        String user = credentials[0];
        String pwd = credentials[1];
        try {
            CredentialsProvider provider = new BasicCredentialsProvider(); //凭证提供器
            UsernamePasswordCredentials credential = new UsernamePasswordCredentials(user, pwd);//用户凭证
            provider.setCredentials(AuthScope.ANY, credential);

            HttpClient client = HttpClientBuilder.create()
                    .setDefaultCredentialsProvider(provider)
                    .build();
            HttpResponse responce = client.execute(new HttpGet(url));
            // get http status code
            int resStatu = responce.getStatusLine().getStatusCode();
            if (resStatu == HttpStatus.SC_OK) {
                // get result data
                HttpEntity entity = responce.getEntity();
                result = EntityUtils.toString(entity);
            } else {
                log.error(url + ": resStatu is " + resStatu);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 发送 get请求
     */
    public static String get(String url, Map<String, String> requestParameters, int timeOut, String charset) {
        List<NameValuePair> params = null;
        if (requestParameters != null) {
            params = new ArrayList<NameValuePair>();
            Iterator<Map.Entry<String, String>> it = requestParameters.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }
        return get(url, params, null, timeOut, charset);
    }

    /**
     * 发送 get请求
     *
     * @param url     请求地址
     * @param params  参数
     * @param headers 头部信息
     * @param timeOut 超时时间
     * @param charset 字符编码
     * @return
     */
    public static String get(String url, List<NameValuePair> params, Map<String, String> headers, int timeOut, String charset) {
        String resultStr = null;
        //1.创建HttpCient实例
        HttpClient httpClient = null;
        //2.创建get请求
        HttpGet httpGet = null;
        try {
            httpClient = HttpClients.createDefault();

            URIBuilder uri = new URIBuilder();
            uri.setPath(url); //请求地址
            if (params != null) {
                uri.addParameters(params); //构建参数
            }
            httpGet = new HttpGet(url);
            if (null != headers) {
                httpGet.setHeaders(assemblyHeader(headers)); //设置头部
            }
            RequestConfig requestConfig = RequestConfig.custom()  //设置请求和传输时间等
                    .setConnectionRequestTimeout(timeOut)
                    .setConnectTimeout(timeOut)
                    .setSocketTimeout(timeOut)
                    .build();
            httpGet.setConfig(requestConfig);

            //3.执行请求
            HttpResponse responce = httpClient.execute(httpGet);

            //4.获取响应
            if (responce.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = responce.getEntity(); //返回内容实体
                if (entity != null && entity.isStreaming()) {
                    InputStream instream = entity.getContent();  //文件
                    BufferedReader reader = new BufferedReader(new InputStreamReader(instream, charset));
                    StringBuffer sb = new StringBuffer();
                    try {
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                            sb.append(line + "\n");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        EntityUtils.consume(entity); //关闭流
                        if (instream != null) instream.close();
                    }
                    resultStr = sb.toString();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultStr;
    }

    //这是组装头部
    public static Header[] assemblyHeader(Map<String, String> headers) {
        Header[] allHeader = new BasicHeader[headers.size()];
        int i = 0;
        for (String str : headers.keySet()) {
            allHeader[i] = new BasicHeader(str, headers.get(str));
            i++;
        }
        return allHeader;
    }

    public static String post(String url) {
        return post(null, null, null, null, url, "utf-8", 60 * 1000);
    }

    public static String post(Map<String, String> params, String url) {
        return post(null, null, null, params, url, "utf-8", 60 * 1000);
    }

    /**
     * @param user       用户名
     * @param pwd        密码
     * @param headers    头信息
     * @param parameters 参数
     * @param url        地址
     * @param unicode    编码 utf-8  gbk
     * @param timeOut    超时时间
     * @return
     */
    public static String post(String user, String pwd, Map<String, String> headers,
                              Map<String, String> parameters, String url, String unicode, int timeOut) {
        String resultStr = null;
        //1.创建httpClient
        DefaultHttpClient httpClient = null;
        //2.创建请求
        HttpPost httpPost = null;
        try {
            httpClient = new DefaultHttpClient();

            httpPost = new HttpPost(url);
            if (headers != null) {
                httpPost.setHeaders(assemblyHeader(headers)); //设置头部
            }
            RequestConfig config = RequestConfig.custom() //设置请求和传输时间等
                    .setConnectionRequestTimeout(timeOut)
                    .setConnectTimeout(timeOut)
                    .setSocketTimeout(timeOut)
                    .build();
            httpPost.setConfig(config);
            List<NameValuePair> params = new ArrayList<NameValuePair>();// 使用NameValuePair来保存要传递的Post参数
            if (parameters != null && !parameters.isEmpty()) {
                Iterator<Map.Entry<String, String>> it = parameters.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
            }
            HttpEntity httpentity = new UrlEncodedFormEntity(params, unicode);   // 设置字符集
            httpPost.setEntity(httpentity);

            HttpContext localContext = new BasicHttpContext();
            if (user != null && pwd != null) {
                AuthScope authScope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);
                CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); //凭证提供器
                UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, pwd);//用户凭证
                credentialsProvider.setCredentials(authScope, creds);
                httpClient.setCredentialsProvider(credentialsProvider);

                localContext.setAttribute(ClientContext.CREDS_PROVIDER, credentialsProvider);
            }
            //3.执行请求
            HttpResponse httpResponse = httpClient.execute(httpPost, localContext);

            //4.获取响应
            System.out.println(httpResponse.getStatusLine().getStatusCode());
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = httpResponse.getEntity();
                InputStream instream = entity.getContent();
                StringBuffer sb = new StringBuffer();
                try {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    EntityUtils.consume(entity);
                    try {
                        if (instream != null) instream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                resultStr = sb.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultStr;
    }

    //编码转换
    public static String urlEncode(String url, String encode) {
        String str = null;
        try {
            str = URLEncoder.encode(url, encode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    //==================================================================================================================

    /*获取存入Session的信息,返回对象形式*/
    public static <T> T getSessionObj(String key,Class<T> T){
        HttpSession session = getCurSession();
        if( session == null){
            return null;
        }
        Object obj = session.getAttribute(key);
        if(obj == null){
            return null;
        }
        return (T) obj;
    }

    /*获取当前Request*/
    public static HttpServletRequest getCurRequest() {
        return getServletRequestAttributes() == null ? null : getServletRequestAttributes().getRequest();
    }

    /*获取当前Session*/
    public static HttpSession getCurSession() {
        return   getServletRequestAttributes() == null ? null : getServletRequestAttributes().getRequest().getSession();
    }

    public static ServletRequestAttributes getServletRequestAttributes() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null != attributes) {
            return attributes;
        } else {
            return null;
        }
    }

    public static void main(String[] args) {
        getCurRequest().setAttribute("","");
        getCurRequest().getAttribute("");
        getCurRequest().getParameter("");
        getCurRequest().getParameterMap();
    }
}
